package com.tom.architect02.zframework.hook.hook3;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.IntentFilter;
import android.content.pm.PackageManager;

import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
import dalvik.system.DexClassLoader;


/**
 * Added by Tom on 2024/04/03.
 * 反射拿到PackageParser
 */
public class MyPackageParser {
    //    系统兼容性问题。
//    hook   ---- 不影响  系统的执行    系统的信息     hook
    public void parserReceivers(Context context, File apkFile) throws Exception {
        Class<?> packageParserClass = Class.forName("android.content.pm.PackageParser");
        Method parsePackageMethod = packageParserClass.getDeclaredMethod("parsePackage", File.class, int.class);
        parsePackageMethod.setAccessible(true);
        Object packageParser = packageParserClass.newInstance();

        // 通过反射构建
        Object packageObj = parsePackageMethod.invoke(packageParser, apkFile, PackageManager.GET_RECEIVERS);
        // packageObj.hashCode();
        Field receiversField = packageObj.getClass().getDeclaredField("receivers"); // 新apk的receivers
        List receivers = (List) receiversField.get(packageObj);

        // AndroidManifest 存档信息---> Package对象   描述信息,
        // 类加载器，手动将apk加载出来。apk路径；dex提取出来存放的路径；库的路径；ClassLoader
        DexClassLoader dexClassLoader = new DexClassLoader(apkFile.getAbsolutePath(),
                context.getDir("plugin", Context.MODE_PRIVATE).getAbsolutePath(),
                null, context.getClassLoader());
        // *动态注册*
        Class<?> componentClass = Class.forName("android.content.pm.PackageParser$Component");
        Field intentsField = componentClass.getDeclaredField("intents");
        for (Object receiverObject : receivers) {
            // 拿到全类名 eg: com.maniu.receiver.DavidReceiver
            String name = (String) receiverObject.getClass().getField("className").get(receiverObject);
            // class  ---> 对象
            try {
                // 通过类加载器，加载 BroadcastReceiver 对象.
                BroadcastReceiver broadcastReceiver = (BroadcastReceiver) dexClassLoader.loadClass(name).newInstance();
                List<? extends IntentFilter> filters = (List<? extends IntentFilter>) intentsField.get(receiverObject);
                // intent 可以有多个 IntentFilter(action)
                for (IntentFilter filter : filters) {
                    context.registerReceiver(broadcastReceiver, filter);
                }
            } catch (Exception e) {
            }
            // 下发的广播，就可以运行了。
        }
    }

}
